package archer.framework.utils;

import jodd.bean.BeanUtil;
import jodd.json.*;
import jodd.typeconverter.Convert;

import java.util.*;

/**
 * Map工具类
 *
 * @author christ
 * @date 2016/3/31
 */
public class MapUtils {

    /**
     * bean -> map
     *
     * @param bean
     * @return
     */
    public static Map fromBean(Object bean, String... ignoreFields) {

        return fromBean(bean, true, ignoreFields);
    }

    public static Map fromBean(Object bean, final boolean ignoreNull, final String... ignoreFields) {

        final Map result = new HashMap();

        JsonContext jsonContext = new JsonSerializer().deep(true).createJsonContext(null);

        BeanSerializer beanSerializer = new BeanSerializer(jsonContext, bean) {
            @Override
            protected void onSerializableProperty(String propertyName, Class propertyType, Object value) {

                // 如果需要移除null，且当前值为null
                if (ignoreNull && value == null) {
                    return;
                }

                if (ignoreFields != null) {
                    for (String each : ignoreFields) {
                        // 如果在忽略字段中
                        if (propertyName.equals(each)) {
                            return;
                        }
                    }
                }

                result.put(propertyName, value);
            }
        };
        beanSerializer.serialize();
        return result;
    }

    /**
     * bean -> map
     * <br>内部对象也会被转为map<br/>
     *
     * @param bean
     * @return
     */
    public static Map fromBeanDeeply(Object bean) {

        return JSONUtils.deserialize(JSONUtils.serialize(bean), Map.class);
    }

    /**
     * 数组 -> Map
     *
     * @param data
     * @return
     */
    public static Map asMap(Object... data) {

        if (data.length % 2 == 1) {
            throw new IllegalArgumentException("数组长度必须为2的倍数");
        }

        Map map = new HashMap();
        for (int i = 0; i < data.length; ) {
            map.put(data[i++], data[i++]);
        }
        return map;
    }

    /**
     * 强制转型
     *
     * @param object
     * @return
     */
    public static Map cast(Object object) {

        return (Map) object;
    }

    /**
     * 获取string类型的值
     *
     * @param map
     * @param key
     * @return
     */
    public static String getString(Map map, String key) {

        return (String) getValue(map, key);
    }

    /**
     * 获得integer类型的值
     *
     * @param map
     * @param key
     * @return
     */
    public static Integer getInteger(Map map, String key) {

        return (Integer) getValue(map, key);
    }

    /**
     * 获取值
     *
     * @param map
     * @param key
     * @return
     */
    public static Object getValue(Map map, String key) {

        if (ValidateUtils.isEmpty(map)) {
            return null;
        }
        return map.get(key);
    }

    /**
     * 根据给定的字段分组
     *
     * @param src
     * @param fields
     * @param <T>
     * @return
     */
    public static <T> Map<String, T> groupByFields(Collection<T> src, String... fields) {

        return groupByFields(",", src, fields);
    }

    /**
     * 根据给定的字段分组
     *
     * @param src
     * @param separator
     * @param fields
     * @param <T>
     * @return
     */
    public static <T> Map<String, T> groupByFields(String separator, Collection<T> src, Object... fields) {

        if (ValidateUtils.isEmpty(src)) {
            return new HashMap<String, T>();
        }

        Map<String, T> map = new HashMap<String, T>();
        for (T each : src) {

            String key;
            List<String> keys = new ArrayList<String>();
            for (Object field : fields) {
                keys.add(Convert.toString(BeanUtil.pojo.getProperty(each, (String) field)));
            }

            key = StringUtils.join(keys, separator);

            if (key != null) {
                map.put(key, each);
            }

        }
        return map;
    }

    /**
     * 按照给定字段分组
     *
     * @param src
     * @param fields
     * @param <T>
     * @return
     */
    public static <T> Map<String, List<T>> groupByFieldsDeeply(Collection<T> src, Object... fields) {

        return groupByFieldsDeeply(src, ",", fields);
    }

    /**
     * 按照给定字段分组
     *
     * @param src
     * @param separator
     * @param fields
     * @param <T>
     * @return
     */
    public static <T> Map<String, List<T>> groupByFieldsDeeply(Collection<T> src, String separator, Object... fields) {

        if (ValidateUtils.isEmpty(src)) {
            return new HashMap<String, List<T>>();
        }

        Map<String, List<T>> map = new HashMap<String, List<T>>();
        for (T each : src) {

            String key;
            List<String> keys = new ArrayList<String>();
            for (Object field : fields) {
                keys.add(Convert.toString(BeanUtil.pojo.getProperty(each, (String) field)));
            }

            key = StringUtils.join(keys, separator);

            if (key != null) {
                List<T> list = map.get(key);
                if (list == null) {
                    list = new ArrayList<>();
                    map.put(key, list);
                }
                list.add(each);
            }

        }
        return map;
    }

    /**
     * map转bean
     *
     * @param src
     * @param target
     * @param <T>
     * @return
     */
    public static <T> T toBean(Map src, Class<T> target) {

        if (ValidateUtils.isEmpty(src)) {
            return null;
        }

        return (T) new MapToBean(new JsonParser(), target.getName()).map2bean(src, target);
    }

    public static <T> List<T> toBean(List<Map<String, ?>> src, Class<T> target) {

        List<T> result = new ArrayList<T>();

        for (Map each : src) {
            T bean = toBean(each, target);
            if (bean != null) {
                result.add(bean);
            }
        }
        return result;
    }

}
